package com.greenbook.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.greenbook.dto.LikeOrCollectDTO;
import com.greenbook.dto.NoteDOC;
import com.greenbook.dto.NoteDTO;
import com.greenbook.dto.PageDTO;
import com.greenbook.entity.*;
import com.greenbook.mapper.*;
import com.greenbook.service.NoteSearchService;
import com.greenbook.service.NoteService;
import com.greenbook.vo.NoteCoverVO;
import com.greenbook.vo.NoteVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.User;
import org.springframework.beans.BeanUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class NoteServiceImpl implements NoteService {
    private final NoteMapper noteMapper;
    private final NoteTagMapper noteTagMapper;
    private final NoteImageMapper noteImageMapper;
    private final NoteSearchService noteSearchService;
    private final UserInfoMapper userInfoMapper;
    private final NoteCategoryMapper noteCategoryMapper;
    private final NoteLikeMapper noteLikeMapper;
    private final UserStatisticsMapper userStatisticsMapper;
    private final NoteCollectionMapper noteCollectionMapper;
    /**
     * 保存笔记
     *
     * @param noteDTO 笔记DTO对象
     */
    @Override
    public void save(NoteDTO noteDTO) {
        // 1. 拷贝属性
        Note note = new Note();
        BeanUtils.copyProperties(noteDTO, note);
        // 2. 设置属性
        Long userId = Long.parseLong(SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString());
        note.setUserId(userId);
        // 暂时设置为1，方便初期展示
        note.setRecommend(1);
        // 第一张图片作为封面
        note.setCoverImage(noteDTO.getFileList().getFirst());
        // 设置封面高度
        note.setCoverHeight(noteDTO.getCoverHeight());
        // 3.保存笔记（会自动填充id）
        noteMapper.insert(note);
        // 4.保存标签
        for(String tag : noteDTO.getTagList()) {
            NoteTag noteTag = new NoteTag();
            noteTag.setName(tag);
            noteTag.setNoteId(note.getId());
            noteTagMapper.insert(noteTag);
        }
        // 5.保存笔记图片
        for(String file : noteDTO.getFileList()) {
            NoteImage noteImage = new NoteImage();
            noteImage.setNoteId(note.getId());
            noteImage.setUrl(file);
            noteImageMapper.insert(noteImage);
        }
        // 6.同步到es
        NoteDOC noteDoc = new NoteDOC();
        note = noteMapper.selectById(note.getId());
        BeanUtils.copyProperties(note, noteDoc);
        noteDoc.setId(note.getId().toString());
        // 6.1查找用户信息
        LambdaQueryWrapper<UserInfo> userInfoWrapper = new LambdaQueryWrapper<>();
        userInfoWrapper.eq(UserInfo::getUserId, userId);
        UserInfo userInfo = userInfoMapper.selectOne(userInfoWrapper);
        noteDoc.setUserId(userInfo.getUserId());
        noteDoc.setNickname(userInfo.getNickname());
        noteDoc.setAvatar(userInfo.getAvatar());
        // 6.2查询笔记分类
        LambdaQueryWrapper<NoteCategory> noteCategoryWrapper = new LambdaQueryWrapper<>();
        noteCategoryWrapper.eq(NoteCategory::getId, note.getCategoryId());
        NoteCategory noteCategory = noteCategoryMapper.selectOne(noteCategoryWrapper);
        noteDoc.setNoteCategory(noteCategory.getTitle());
        // 添加标签
        noteDoc.setTags(noteDTO.getTagList());
        noteSearchService.saveNoteDoc(noteDoc);
    }

    /**
     * 根据笔记Id查询笔记
     * @param noteId
     * @return
     */
    @Override
    public NoteVO getNoteById(Long noteId) {
        Long currentUser = Long.parseLong(SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString());
        // 1.查询笔记
        LambdaQueryWrapper<Note> noteWrapper = new LambdaQueryWrapper<>();
        noteWrapper.eq(Note::getId, noteId);
        Note note = noteMapper.selectOne(noteWrapper);
        // 2.查询标签
        LambdaQueryWrapper<NoteTag> noteTagWrapper = new LambdaQueryWrapper<>();
        noteTagWrapper.eq(NoteTag::getNoteId, noteId)
                .select(NoteTag::getName);
        List<String> tags = noteTagMapper.selectObjs(noteTagWrapper)
                .stream()
                .map(obj -> (String) obj)
                .toList();
        // 3.查询图片
        LambdaQueryWrapper<NoteImage> noteImageWrapper = new LambdaQueryWrapper<>();
        noteImageWrapper.eq(NoteImage::getNoteId, noteId)
                .select(NoteImage::getUrl);
        List<String> images = noteImageMapper.selectObjs(noteImageWrapper)
                .stream()
                .map(obj -> (String) obj)
                .toList();
        // 4.查询作者
        LambdaQueryWrapper<UserInfo> userInfoWrapper = new LambdaQueryWrapper<>();
        userInfoWrapper.eq(UserInfo::getUserId, note.getUserId())
                .select(UserInfo::getNickname, UserInfo::getAvatar);
        UserInfo userInfo = userInfoMapper.selectOne(userInfoWrapper);
        // 5.封装视图对象
        NoteVO noteVO = new NoteVO();
        // 5.1 拷贝笔记属性
        BeanUtils.copyProperties(note, noteVO);
        // 5.2 设置标签
        noteVO.setTags(tags);
        // 5.3 设置图片
        noteVO.setImages(images);
        // 5.4 设置作者
        noteVO.setNickname(userInfo.getNickname());
        noteVO.setAvatar(userInfo.getAvatar());
        // 5.5 设置当前用户是否点赞
        Long likeCount = noteLikeMapper.selectCount(new LambdaQueryWrapper<NoteLike>()
                .eq(NoteLike::getUserId, currentUser)
                .eq(NoteLike::getNoteId, noteId));
        if(likeCount == 1) {
            noteVO.setIsLiked(true);
        }
        Long collectCount = noteCollectionMapper.selectCount(new LambdaQueryWrapper<NoteCollection>()
                .eq(NoteCollection::getUserId, currentUser)
                .eq(NoteCollection::getNoteId, noteId));
        if(collectCount == 1) {
            noteVO.setIsCollected(true);
        }
        return noteVO;
    }

    @Override
    public PageDTO<NoteCoverVO> pageByUserId(Integer currentPage, Integer pageSize, Long userId, Integer type) {
        // 0.构建分页查询条件
        Page<Note> page = new Page<>(currentPage, pageSize);
        LambdaQueryWrapper<Note> noteWrapper = new LambdaQueryWrapper<>();
        noteWrapper.eq(Note::getUserId, userId)
                .orderByDesc(Note::getUpdateTime);  // 根据更新时间降序排序
        // 1.执行分页查询
        Page<Note> notePage = noteMapper.selectPage(page, noteWrapper);
        // 2.获取查询结果
        List<Note> noteList = notePage.getRecords();
        // 3.构建视图对象
        List<NoteCoverVO> noteCoverVOList = new ArrayList<>();
        for(Note note : noteList) {
            NoteCoverVO noteCoverVO = new NoteCoverVO();
            BeanUtils.copyProperties(note, noteCoverVO);
            // 3.1查询封面图片
            LambdaQueryWrapper<NoteImage> noteImageWrapper = new LambdaQueryWrapper<>();
            noteImageWrapper.eq(NoteImage::getNoteId, note.getId())
                    .select(NoteImage::getUrl);
            List<String> noteImageList = noteImageMapper.selectObjs(noteImageWrapper)
                    .stream().map(obj -> (String) obj).toList();
            noteCoverVO.setCoverImage(noteImageList.getFirst());
            // 3.2查询用户信息
            LambdaQueryWrapper<UserInfo> userInfoWrapper = new LambdaQueryWrapper<>();
            userInfoWrapper.eq(UserInfo::getUserId, userId)
                    .select(UserInfo::getNickname, UserInfo::getAvatar);
            UserInfo userInfo = userInfoMapper.selectOne(userInfoWrapper);
            noteCoverVO.setUserId(userInfo.getUserId());
            noteCoverVO.setNickname(userInfo.getNickname());
            noteCoverVO.setAvatar(userInfo.getAvatar());
            noteCoverVOList.add(noteCoverVO);
        }
        // 4.封装分页结果
        PageDTO<NoteCoverVO> pageDTO = new PageDTO<>();
        pageDTO.setTotal(notePage.getTotal());
        pageDTO.setRecords(noteCoverVOList);
        return pageDTO;
    }

    /**
     * 文章点赞
     * @param likeOrCollectDTO
     */
    @Override
    public void likeOrCollect(LikeOrCollectDTO likeOrCollectDTO) {
        Long userId = likeOrCollectDTO.getUserId();
        Long noteId = likeOrCollectDTO.getNoteId();
        Integer type = likeOrCollectDTO.getType();
        Long currentUser = (Long) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        // 1.查询笔记
        LambdaQueryWrapper<Note> noteWrapper = new LambdaQueryWrapper<>();
        noteWrapper.eq(Note::getId, noteId);
        Note note = noteMapper.selectOne(noteWrapper);
        // 如果笔记不存在，抛出异常
        if(note == null) {
            throw new RuntimeException("笔记不存在");
        }
        // 构造用户统计信息
        LambdaUpdateWrapper<UserStatistics> userStatisticsWrapper = new LambdaUpdateWrapper<>();
        // 2.构造点赞或收藏表
        if(type == 1) {
            // 3. 查询是否已经点赞
            LambdaQueryWrapper<NoteLike> noteLikeWrapper = new LambdaQueryWrapper<>();
            noteLikeWrapper.eq(NoteLike::getUserId, currentUser)
                   .eq(NoteLike::getNoteId, noteId);
            NoteLike noteLike = noteLikeMapper.selectOne(noteLikeWrapper);
            if(noteLike == null) {
                // 3.1 如果没有点赞，则插入点赞记录
                noteLike = new NoteLike();
                noteLike.setUserId(currentUser);    // 点赞用户
                noteLike.setNoteId(noteId);         // 点赞笔记
                noteLikeMapper.insert(noteLike);
                // 3.2 更新笔记点赞数
                note.setLikeCount(note.getLikeCount() + 1);
                // 3.3 更新作者统计信息
                userStatisticsWrapper.eq(UserStatistics::getUserId, userId)
                        .setIncrBy(UserStatistics::getLikedCount, 1);
                userStatisticsMapper.update(userStatisticsWrapper);
                // 3.4 更新当前用户统计信息
                userStatisticsWrapper.clear();
                userStatisticsWrapper.eq(UserStatistics::getUserId, currentUser)
                        .setIncrBy(UserStatistics::getLikeCount, 1);
                userStatisticsMapper.update(userStatisticsWrapper);
                //TODO 3.5同步到es
                //TODO 增加并发控制和异步消息队列处理
            } else {
                // 3.1 如果已经点赞，则删除点赞记录
                noteLikeMapper.delete(noteLikeWrapper);
                // 3.2 更新笔记点赞数
                note.setLikeCount(note.getLikeCount() - 1);
                // 3.3 更新作者统计信息
                userStatisticsWrapper.eq(UserStatistics::getUserId, userId)
                        .setDecrBy(UserStatistics::getLikedCount, 1);
                userStatisticsMapper.update(userStatisticsWrapper);
                // 3.4 更新当前用户统计信息
                userStatisticsWrapper.clear();
                userStatisticsWrapper.eq(UserStatistics::getUserId, currentUser)
                       .setDecrBy(UserStatistics::getLikeCount, 1);
                userStatisticsMapper.update(userStatisticsWrapper);
            }
        } else {
            // 3. 查询是否已经收藏
            LambdaQueryWrapper<NoteCollection> noteCollectionWrapper = new LambdaQueryWrapper<>();
            noteCollectionWrapper.eq(NoteCollection::getUserId, currentUser)
                    .eq(NoteCollection::getNoteId, noteId);
            NoteCollection noteCollection = noteCollectionMapper.selectOne(noteCollectionWrapper);
            if(noteCollection == null) {
                // 3.1 如果没有收藏，则插入收藏记录
                noteCollection = new NoteCollection();
                noteCollection.setUserId(currentUser);    // 点赞用户
                noteCollection.setNoteId(noteId);         // 点赞笔记
                noteCollectionMapper.insert(noteCollection);
                // 3.2 更新笔记收藏数
                note.setCollectCount(note.getCollectCount() + 1);
                // 3.3 更新作者统计信息
                userStatisticsWrapper.eq(UserStatistics::getUserId, userId)
                        .setIncrBy(UserStatistics::getCollectedCount, 1);
                userStatisticsMapper.update(userStatisticsWrapper);
                // 3.4 更新当前用户统计信息
                userStatisticsWrapper.clear();
                userStatisticsWrapper.eq(UserStatistics::getUserId, currentUser)
                        .setIncrBy(UserStatistics::getCollectCount, 1);
                userStatisticsMapper.update(userStatisticsWrapper);
                //TODO 3.5同步到es
                //TODO 增加并发控制和异步消息队列处理
            } else {
                // 3.1 如果已经收藏，则删除收藏记录
                noteCollectionMapper.delete(noteCollectionWrapper);
                // 3.2 更新笔记收藏数
                note.setCollectCount(note.getCollectCount() - 1);
                // 3.3 更新作者统计信息
                userStatisticsWrapper.eq(UserStatistics::getUserId, userId)
                       .setDecrBy(UserStatistics::getCollectedCount, 1);
                userStatisticsMapper.update(userStatisticsWrapper);
                // 3.4 更新当前用户统计信息
                userStatisticsWrapper.clear();
                userStatisticsWrapper.eq(UserStatistics::getUserId, userId)
                        .setDecrBy(UserStatistics::getCollectCount, 1);
                userStatisticsMapper.update(userStatisticsWrapper);
            }
        }
        noteMapper.updateById(note);
    }
}
